﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PeoplesJukebox.Core.TrackLists.Bases;
using PeoplesJukebox.Core.MediaItems;
using config = PeoplesJukebox.Core.Configuration;

namespace PeoplesJukebox.Core.TrackLists
{
    /// <summary>
    /// Tracklist which selects the next track at random
    /// </summary>
    public class RandomTrackList : TrackListBase
    {
        private bool _includeMustHaves;
        private int _randomTrackCount;
        private int _totalTrackCount;
        private int _mustHaveTrackIndex;

        /// <summary>
        /// Default constructor
        /// </summary>
        public RandomTrackList() { }

        /// <summary>
        /// Gets the name of the tracklist
        /// </summary>
        public override string Name
        {
            get { return "Random";  }
        }

        /// <summary>
        /// Returns whether there are any unplayed tracks left
        /// </summary>
        public override bool HasTracks
        {
            get { return PlayedTracks.Count < this._totalTrackCount; }
        }

        /// <summary>
        /// Gets the ID of the next track to play
        /// </summary>
        /// <remarks>
        /// Will either be a random track ID, or one of the configured "must-have" tracks
        /// </remarks>
        /// <returns>Track ID</returns>
        protected override int GetNextTrackId()
        {
            int trackId = -1;
            //next track is either a random one from the catalogue, or
            //the next in the must-have list:
            if (this._includeMustHaves && 
                this._randomTrackCount >= config.RandomTrackListConfiguration.Current.MustHaveTrackFrequency &&
                config.RandomTrackListConfiguration.Current.MustHaveTracks.Count > this._mustHaveTrackIndex)
            {
                trackId = this.GetConfiguredTrackId(config.RandomTrackListConfiguration.Current.MustHaveTracks, this._mustHaveTrackIndex);
                this._mustHaveTrackIndex++;
                this._randomTrackCount = 0;
            }
            //if we're not using must-haves, or the must-have isn't found, use random:
            if (trackId == -1)
            {
                trackId = Container.Catalogue.GetRandomTrack().Id;
                this._randomTrackCount++;
            }
            return trackId;
        }

        /// <summary>
        /// Loads the track selection
        /// </summary>
        public override void Load()
        {
            base.Load();
            //record total track count:
            this._totalTrackCount = Container.Catalogue.Tracks.Count;
            this._randomTrackCount = 0;
            //record if there's configuration for must-have tracks:
            this._includeMustHaves = config.RandomTrackListConfiguration.Current != null &&
                                     config.RandomTrackListConfiguration.Current.MustHaveTracks.Count > 0;
        }

        /// <summary>
        /// Returns a random list of unplayed tracks
        /// </summary>
        /// <remarks>
        /// If all tracks have been played, returns empty list
        /// </remarks>
        /// <param name="count">Number of tracks to return</param>
        /// <returns>List of random unplayed tracks</returns>
        public List<Track> GetRandomUnplayedTracks(int count)
        {
            Dictionary<int, Track> randomTracks = new Dictionary<int, Track>(count);
            while (randomTracks.Count < count && this.HasTracks)
            {
                Track track = Container.Catalogue.GetRandomTrack();
                if (!PlayedTracks.Contains(track.Id) && !randomTracks.ContainsKey(track.Id))
                {
                    randomTracks.Add(track.Id, track);
                }
            }
            return randomTracks.Values.ToList();
        }
    }
}
